package com.carolouvindam.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.widget.Toast;
import com.carolouvindam.Application;
import com.carolouvindam.Model.Address;
import com.carolouvindam.Model.Client;
import com.carolouvindam.Model.Order;
import com.carolouvindam.Model.Product;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class DataSource {
    private Context context;
    private OurSQLiteOpenHelper dbHelper;
    private SQLiteDatabase database;


    public DataSource(Context context) {
        this.context = context;
    }

    public DataSource open() throws SQLException {
        this.dbHelper = new OurSQLiteOpenHelper(context);
        this.database = this.dbHelper.getWritableDatabase();
        return this;
    }

    public void BourrageInutilePourLeDebug() {
        Order order = new Order(
                null,
                new Client(
                        "Cotro",
                        "Vincent",
                        "06666666"
                ),
                new Address(
                        "62 bd de la Liberté",
                        null,
                        "Lille",
                        "59800"
                ),
                new ArrayList<Product>(),
                new Date());
        order.getProduits().add(Application.CAKES[5]);
        order.getProduits().add(Application.CAKES[5]);
        order.getProduits().add(Application.CAKES[5]);
        insert(order);

    }

    public void close() {
        dbHelper.close();
    }

    private ContentValues orderToContentValues(Order order) {
        ContentValues values = new ContentValues();
        values.put(OrderTable.CLIENT_NAME, order.getClient().getName());
        values.put(OrderTable.CLIENT_FIRSTNAME, order.getClient().getFirstName());
        values.put(OrderTable.CLIENT_PHONE, order.getClient().getPhoneNumber());
        values.put(OrderTable.DATE, order.getDate().getTime());
        values.put(OrderTable.ADDRESS_LINE1, order.getAddress().getLine1());
        values.put(OrderTable.ADDRESS_LINE2, order.getAddress().getLine2());
        values.put(OrderTable.ADDRESS_CITY, order.getAddress().getCity());
        values.put(OrderTable.ADDRESS_POSTALCODE, order.getAddress().getPostalCode());
        return values;
    }

    public long insert(Order order) {
        ContentValues values = orderToContentValues(order);
        order.setIdDB(database.insert(OrderTable.TABLESNAME, null, values));
        addProductToOrder(order);
        return order.getIdDB();
    }

    private long addProductToOrder(Order order) {
        for (Product p : order.getProduits()) {
            ContentValues value = new ContentValues();
            value.put(OrderHasProductTable.ORDERID, order.getIdDB());
            value.put(OrderHasProductTable.PRODUCTID, p.getIdDb());
            database.insert(OrderHasProductTable.TABLESNAME, null, value);
        }
        return order.getIdDB();
    }

    private long deleteProductFromOrder(Order order) {
        return database.delete(OrderHasProductTable.TABLESNAME, OrderHasProductTable.ORDERID + " = ?", new String[]{order.getIdDB().toString()});
    }

    public long update(Order order) {
        ContentValues values = orderToContentValues(order);
        database.update(OrderTable.TABLESNAME, values, OrderTable.ID + " = ?", new String[]{order.getIdDB().toString()});
        deleteProductFromOrder(order);
        addProductToOrder(order);
        return order.getIdDB();
    }

    public long delete(Order order) {
        this.deleteProductFromOrder(order);
        return database.delete(OrderTable.TABLESNAME, OrderTable.ID + " = ?", new String[]{order.getIdDB().toString()});
    }

    private Cursor fetchOne(Integer idDB) {
        return database.query(OrderTable.TABLESNAME, OrderTable.ALLFIELDS, OrderTable.ID + " = ?", new String[]{idDB.toString()}, null, null, null);
    }

    private Cursor fetchAll() {
        return database.query(OrderTable.TABLESNAME, OrderTable.ALLFIELDS, null, null, null, null, null);
    }

    private Cursor fetchAllOrderByTime() {
        return database.query(OrderTable.TABLESNAME, OrderTable.ALLFIELDS, null, null, null, null, OrderTable.DATE);
    }
    
    private Cursor fetchProducts(Order order) {
        return database.query(OrderHasProductTable.TABLESNAME, new String[]{OrderHasProductTable.PRODUCTID}, OrderHasProductTable.ORDERID + " = ?", new String[]{order.getIdDB().toString()}, null, null, null);
    }

    private Cursor fetchProducts(Integer idDB) {
        return database.query(OrderHasProductTable.TABLESNAME, new String[]{OrderHasProductTable.PRODUCTID}, OrderHasProductTable.ORDERID + " = ?", new String[]{idDB.toString()}, null, null, null);
    }

    public Order getOne(Integer idDB) {
        Order order = null;
        Cursor cursorOrder = fetchOne(idDB);
        //Recuperer la Commande
        cursorOrder.moveToFirst();
        if (!cursorOrder.isAfterLast()) {
            order = CursorToOrder(cursorOrder);
        }
        cursorOrder.close();
        //Récuperer les Produits
        Cursor cursorProduct = fetchProducts(order);
        cursorProduct.moveToFirst();
        while (!cursorProduct.isAfterLast()) {
            order.getProduits().add(CursorToProduct(cursorProduct));
            cursorProduct.moveToNext();
        }
        cursorProduct.close();
        return order;
    }

    public List<Order> getAll() {
        List<Order> orders = new ArrayList<Order>();
        Cursor cursorOrder = fetchAll();
        //Recuperer la Commande
        cursorOrder.moveToFirst();
        while (!cursorOrder.isAfterLast()) {
            orders.add(CursorToOrder(cursorOrder));
            cursorOrder.moveToNext();
        }
        cursorOrder.close();

        for (Order order : orders) {
            //Récuperer les Produits
            try {
                Cursor cursorProduct = fetchProducts(order);
                cursorProduct.moveToFirst();
                while (!cursorProduct.isAfterLast()) {
                    order.getProduits().add(CursorToProduct(cursorProduct));
                    cursorProduct.moveToNext();
                }
                cursorProduct.close();
            } catch (Exception e) {
                Toast grill = Toast.makeText(this.context, e.getMessage(), Toast.LENGTH_LONG);
                grill.show();
            }
        }
        return orders;
    }

    public List<Order> getAllOrderByTime() {
        List<Order> orders = new ArrayList<Order>();
        Cursor cursorOrder = fetchAllOrderByTime();
        //Recuperer la Commande
        cursorOrder.moveToFirst();
        while (!cursorOrder.isAfterLast()) {
            orders.add(CursorToOrder(cursorOrder));
            cursorOrder.moveToNext();
        }
        cursorOrder.close();

        for (Order order : orders) {
            //Récuperer les Produits
            try {
                Cursor cursorProduct = fetchProducts(order);
                cursorProduct.moveToFirst();
                while (!cursorProduct.isAfterLast()) {
                    order.getProduits().add(CursorToProduct(cursorProduct));
                    cursorProduct.moveToNext();
                }
                cursorProduct.close();
            } catch (Exception e) {
                Toast grill = Toast.makeText(this.context, e.getMessage(), Toast.LENGTH_LONG);
                grill.show();
            }
        }
        return orders;
    }

    private Order CursorToOrder(Cursor cursor) {
        return new Order(cursor.getLong(cursor.getColumnIndexOrThrow(OrderTable.ID)),
                new Client(
                        cursor.getString(cursor.getColumnIndexOrThrow(OrderTable.CLIENT_NAME)),
                        cursor.getString(cursor.getColumnIndexOrThrow(OrderTable.CLIENT_FIRSTNAME)),
                        cursor.getString(cursor.getColumnIndexOrThrow(OrderTable.CLIENT_PHONE))),
                new Address(
                        cursor.getString(cursor.getColumnIndexOrThrow(OrderTable.ADDRESS_LINE1)),
                        cursor.getString(cursor.getColumnIndexOrThrow(OrderTable.ADDRESS_LINE2)),
                        cursor.getString(cursor.getColumnIndexOrThrow(OrderTable.ADDRESS_CITY)),
                        cursor.getString(cursor.getColumnIndexOrThrow(OrderTable.ADDRESS_POSTALCODE))),
                new ArrayList<Product>(),
                new Date(cursor.getLong(cursor.getColumnIndexOrThrow(OrderTable.DATE)))
        );
    }

    private Product CursorToProduct(Cursor cursor) {
        return Application.CAKES[(cursor.getInt(cursor.getColumnIndexOrThrow(OrderHasProductTable.PRODUCTID)))];

    }


}
